import logging
import os
import threading
from functools import lru_cache

# 定义日志格式
LOG_FORMAT = '%(asctime)s - %(levelname)s - [%(name)s %(funcName)s %(lineno)d] - [%(request_id)s] - %(message)s'
# 定义日期格式
DATE_FORMAT = '%Y-%m-%d %H:%M:%S'

# 创建日志目录
LOG_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'logs')
if not os.path.exists(LOG_DIR):
    os.makedirs(LOG_DIR)

# 创建线程本地存储
_thread_locals = threading.local()


# 创建过滤器，为日志添加request_id
class RequestIdFilter(logging.Filter):
    """
    为日志记录添加request_id的过滤器
    使用线程本地存储确保多线程环境下的request_id隔离
    """

    def filter(self, record):
        # 从线程本地存储获取request_id
        record.request_id = getattr(_thread_locals, 'request_id', 'default')
        return True


# 创建全局过滤器实例
request_id_filter = RequestIdFilter()

# 创建格式化器
formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT)

# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
console_handler.addFilter(request_id_filter)

# 创建文件处理器
log_file = os.path.join(LOG_DIR, 'app.log')
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setFormatter(formatter)
file_handler.addFilter(request_id_filter)


@lru_cache(maxsize=128)
def get_logger(name):
    """
    获取配置好的logger实例
    
    Args:
        name (str): logger名称，通常传入__name__
    
    Returns:
        logging.Logger: 配置好的logger实例
    """
    # 创建logger
    logger = logging.getLogger(name)
    # 设置日志级别
    logger.setLevel(logging.DEBUG)

    # 避免重复添加处理器
    if not logger.handlers:
        # 添加控制台处理器
        logger.addHandler(console_handler)
        # 添加文件处理器
        logger.addHandler(file_handler)

        # 添加过滤器
        logger.addFilter(request_id_filter)

    return logger


def set_request_id_for_logger(request_id):
    """
    为当前线程的logger设置request_id
    
    Args:
        request_id (str): 请求ID
    """
    # 将request_id存储到线程本地存储中
    _thread_locals.request_id = request_id


def get_current_request_id():
    """
    获取当前线程的request_id
    
    Returns:
        str: 当前线程的request_id，如果不存在则返回'default'
    """
    # 从线程本地存储获取request_id
    return getattr(_thread_locals, 'request_id', 'default')


def clear_request_id():
    """
    清除当前线程的request_id
    """
    # 检查并删除线程本地存储中的request_id
    if hasattr(_thread_locals, 'request_id'):
        delattr(_thread_locals, 'request_id')
